package cn.easyutil.deploy.executor;

import cn.easyutil.deploy.base.SystemType;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

/**
 * 指令执行基类
 */
public abstract class AbstractExecutor {

    //最大中断时间,-1默认不中断
    public long interruptConsoleMaxTime = -1;
    //中断标识
    public String interruptConsoleText;
    //输出字符集
    public String consoleCharSet = SystemType.current().getCharset();
    //是否等待执行
    public boolean isWaitFor = true;
    //是否立即中断
    protected boolean interrupt;
    //默认回调器
    protected CommandResultCallBack callBack = System.out::println;

    /**
     * 执行命令
     * @param cmds  多条命令集合
     */
    public abstract void exec(List<String> cmds);

    /**
     * 读取控制台返回内容
     * @param in    控制台返回的流
     */
    protected void print(InputStream in){
        new Thread(() -> {
            long start = System.currentTimeMillis();
            try(BufferedReader read = new BufferedReader(new InputStreamReader(in,consoleCharSet))) {
                String line = null;
                while((line = read.readLine()) != null) {
                    callBack.callBack(line);
                    if(interruptConsoleText!=null && line.trim().toUpperCase().contains(interruptConsoleText.trim().toUpperCase())){
                        //设置立即中断
                        interrupt = true;
                        return ;
                    }
                    long now = System.currentTimeMillis();
                    if(interruptConsoleMaxTime>0 && now-start>interruptConsoleMaxTime){
                        //设置立即中断
                        interrupt = true;
                        return ;
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }finally {
                synchronized (this){
                    this.notifyAll();
                }
            }
        }).start();
    }

    public void exec(Runnable run){

        Thread t1= new Thread(run);
        t1.setDaemon(true);
        t1.start();

        new Thread(() -> {
            while (true){
                try {
                    Thread.sleep(200);
                    if(interrupt){
                        t1.interrupt();
                        return;
                    }
                    if(!t1.isAlive()){
                        return;
                    }
                }catch (Exception e){
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }

    protected void setInterruptConsoleMaxTime(Long interruptConsoleMaxTime) {
        if(interruptConsoleMaxTime == null){
            return ;
        }
        this.interruptConsoleMaxTime = interruptConsoleMaxTime;
    }

    protected void setInterruptConsoleText(String interruptConsoleText) {
        this.interruptConsoleText = interruptConsoleText;
    }

    protected void setConsoleCharSet(String consoleCharSet) {
        if(consoleCharSet == null){
            return ;
        }
        this.consoleCharSet = consoleCharSet;
    }

    protected void setWaitFor(Boolean waitFor) {
        if(waitFor == null){
            return ;
        }
        isWaitFor = waitFor;
    }

    public void setCallBack(CommandResultCallBack callBack) {
        if(callBack == null){
            return ;
        }
        this.callBack = callBack;
    }
}
